/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.jfonia.view.symbols;

import org.jfonia.connect5.basics.BasicValueNode;
import org.jfonia.connect5.basics.MutableValueNode;
import org.jfonia.connect5.basics.ValueNode;
import org.jfonia.connect5.numerical.DoubleMaxRelation;
import org.jfonia.connect5.numerical.DoubleSumRelation;
import org.jfonia.connect5.relations.Equal;
import org.jfonia.constants.ViewConstants;
import org.jfonia.view.relations.DoubleInversionRelation;
import org.jfonia.view.relations.RoundMultiplicationRelation;

/**
 *
 * @author Rik Bauwens
 */
public abstract class RankedStaffSymbol extends StaffSymbol implements IRankedStaffSymbol
{
        private MutableValueNode<Double> staffBase;
        private MutableValueNode<Double> postStaffBase;

        private MutableValueNode<Integer> rankNode;

        public RankedStaffSymbol(ValueNode<Double> frameX, ValueNode<Double> staffY,
                           MutableValueNode<Double> staffBase, MutableValueNode<Double> postStaffBase,
                           ValueNode<Double> xNode, MutableValueNode<Double> widthNode,
                           MutableValueNode<Integer> rankNode)
        {
                super(frameX, staffY, xNode, new BasicValueNode<Double>(0.0));
                this.staffBase = staffBase;
                this.postStaffBase = postStaffBase;

                this.rankNode = new BasicValueNode<Integer>(0);
                new Equal(rankNode, this.rankNode);
                //temporary
                ValueNode<Double> noteHeadSpacing = new BasicValueNode(- ViewConstants.STAFF_LINE_SPACING / 2);
                MutableValueNode<Double> rankOffset = new BasicValueNode(0.0);
                new RoundMultiplicationRelation(noteHeadSpacing, rankNode, rankOffset);
                new DoubleSumRelation(staffBase, rankOffset, getYNode());

                //Symbol base offset
                MutableValueNode<Double> symbolBaseOffset = new BasicValueNode(0.0);
                new DoubleInversionRelation(rankOffset, symbolBaseOffset);

                //Automatically set the staffBase
                MutableValueNode<Double> preSymbolHeight = new BasicValueNode(0.0);
                new DoubleSumRelation(symbolBaseOffset, preYNode, preSymbolHeight);
                new DoubleMaxRelation(staffBase, preSymbolHeight);

                //Automatically set the postStaffBase
                MutableValueNode<Double> postSymbolHeight = new BasicValueNode(0.0);
                new DoubleSumRelation(rankOffset, postYNode, postSymbolHeight);
                new DoubleMaxRelation(postStaffBase, postSymbolHeight);

                //The width of this component is determined by the pre and post X
                new DoubleSumRelation(preXNode, postXNode, getWidthNode());
                //The height of this component is determined by the pre and post Y
                new DoubleSumRelation(preYNode, postYNode, getHeightNode());
                //Preferred width
                new Equal(getWidthNode(), widthNode);
                //new Equal(getHeightNode(), heightNode);
        }

        protected MutableValueNode<Double> getPostStaffBase()
        {
                return postStaffBase;
        }

        protected MutableValueNode<Double> getStaffBase()
        {
                return staffBase;
        }

        protected int getRank()
        {
                return rankNode.getValue();
        }

        protected ValueNode<Integer> getRankNode()
        {
                return rankNode;
        }

        public void setRank(int rank)
        {
                rankNode.setValue(rank);
        }
        
        public void decrementRank()
        {
                setRank(getRank() - 1);
        }

        public void incrementRank()
        {
                setRank(getRank() + 1);
        }
}
